﻿using System;
using System.Linq.Expressions;
using Rainr.EFClient.Expressions;

namespace Rainr.EFClient
{
    /// <summary>
    /// 关系表达式逻辑扩展
    /// </summary>
    public static class PredicateExtensions
    {
        /// <summary>
        /// 逻辑”和“的方式合并两个表达式，并返回合并后的表达式。
        /// </summary>
        /// <typeparam name="T">输入参数类型。</typeparam>
        /// <param name="leftExpression">左边的表达式。</param>
        /// <param name="rightExpression">右边的表达式。</param>
        /// <returns>合并后的表达式。</returns>
        public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> leftExpression, Expression<Func<T, bool>> rightExpression)
        {
            var candidateExpr = Expression.Parameter(typeof(T), "candidate");
            var parameterReplacer = new ParameterReplacerVisitor(candidateExpr);
            var left = parameterReplacer.Replace(leftExpression.Body);
            var right = parameterReplacer.Replace(rightExpression.Body);
            var body = Expression.And(left, right);
            return Expression.Lambda<Func<T, bool>>(body, candidateExpr);
        }
        /// <summary>
        /// 逻辑”或“的方式合并两个表达式，并返回合并后的表达式。
        /// </summary>
        /// <typeparam name="T">输入参数类型。</typeparam>
        /// <param name="leftExpression">左边的表达式。</param>
        /// <param name="rightExpression">右边的表达式。</param>
        /// <returns>合并后的表达式。</returns>
        public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> leftExpression, Expression<Func<T, bool>> rightExpression)
        {
            var candidateExpr = Expression.Parameter(typeof(T), "candidate");
            var parameterReplacer = new ParameterReplacerVisitor(candidateExpr);
            var left = parameterReplacer.Replace(leftExpression.Body);
            var right = parameterReplacer.Replace(rightExpression.Body);
            var body = Expression.Or(left, right);
            return Expression.Lambda<Func<T, bool>>(body, candidateExpr);
        }
    }
}
